home *** CD-ROM | disk | FTP | other *** search
/ Megadoom II / MEGADOOM II - iso.7z / MEGADOOM II.ISO / doom / editors / wadfile / warm11 / reject.c < prev    next >
C/C++ Source or Header  |  1994-12-21  |  19KB  |  463 lines

  1. /******************************************************************************
  2.     MODULE:        REJECT.C
  3.     WRITTEN BY:    Robert Fenske, Jr. (rfenske@swri.edu)
  4.                 Southwest Research Institute
  5.                 Electromagnetics Division
  6.                 6220 Culebra
  7.                 San Antonio, Texas 78238-5166
  8.     CREATED:    June 1994
  9.     DESCRIPTION:    This module contains routines to generate the REJECT
  10.             resource.  The REJECT resource is a two-dimensional
  11.             square bit matrix.  Its size is determined by the
  12.             number of sectors: (<# sectors>^2 + 7) / 8 bytes.  Each
  13.             bit is a flag for a sector pair.  So REJECT[s1][s2] is
  14.             zero then any creatures in sector s1 can attack
  15.             anything in sector s2.  A one means no attack is
  16.             allowed.  For most purposes this essesentially reflects
  17.             whether sector s1 can see sector s2.  Which means that
  18.             REJECT[s1][s2] will be the same as REJECT[s2][s1]
  19.             and that REJECT[s1][s1] will always be zero.  But note
  20.             that if REJECT[s1][s1] is one, then any creatures in
  21.             sector s1 will mill about never attacking anything
  22.             within the sector.  The philosophy of this module is
  23.             that REJECT[s1][s2] should be zero if the sectors s1
  24.             and s2 can see each other--this implies that creatures
  25.             can attack from s1 into s2 (and vice versa).  If s1
  26.             and s2 can't see each other then REJECT[s1][s2] should
  27.             be once.  This module generates the REJECT array solely
  28.             based on whether the sectors are in line of sight of
  29.             each other.
  30.  
  31.             This module does not do any error checking on any
  32.             memory allocation.  If any allocation ever fail, this
  33.             module will bomb.
  34.  
  35.             DOOM is a trademark of id Software, Inc.
  36. ******************************************************************************/
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <math.h>
  41. #include "dmglobal.i"
  42.  
  43. #define rside_sect(l)    rinfo.sides[rinfo.lines[l].rsidndx].sectndx
  44. #define lside_sect(l)    rinfo.sides[rinfo.lines[l].lsidndx].sectndx
  45. #define two_sided(l)    (rinfo.lines[l].lsidndx != -1)
  46.  
  47. #define bit_no(s1,s2)    ((s1)*rinfo.nsects+(s2))
  48. #define clr_flag(a,s1,s2) ((a)[bit_no(s1,s2)/8] &= ~(1<<(bit_no(s1,s2)%8)))
  49. #define set_flag(a,s1,s2) ((a)[bit_no(s1,s2)/8] |= (1<<(bit_no(s1,s2)%8)))
  50. #define get_flag(a,s1,s2) ((a)[bit_no(s1,s2)/8] & (1<<(bit_no(s1,s2)%8)))
  51.  
  52. typedef struct REJECT_INFO {
  53.     int nsects;                /* # sectors */
  54.     DOOM_LINE *lines;
  55.     long nlines;
  56.     DOOM_SIDE *sides;
  57.     DOOM_VERT *verts;
  58.     DOOM_BLOCKMAP *blockmap;
  59.     long *A, *B, *C;            /* lines equation constants */
  60.     int ndiv;                /* # divisions tested / line */
  61. } REJECT_INFO;
  62.  
  63. local REJECT_INFO rinfo;            /* REJECT information block */
  64.  
  65. local DOOM_REJECT *Reject,            /* built REJECT block */
  66.                   *Checked;            /* sector pairs checked blk */
  67.  
  68.  
  69. /******************************************************************************
  70.     ROUTINE:    reject_test_point(lndx,d,ndiv,tp)
  71.     WRITTEN BY:    Robert Fenske, Jr.
  72.     CREATED:    June 1994
  73.     DESCRIPTION:    This routine calculates the input line's test point
  74.             given the ratio d/ndiv (i.e., the dth division of ndiv
  75.             divisions).  It calculates the point
  76.                 x = Vfx + d * (Vtx-Vfx) / nd
  77.                 y = Vfy + d * (Vty-Vfy) / nd
  78. ******************************************************************************/
  79. #if defined(ANSI_C)
  80. local void reject_test_point(int lndx, int d, int ndiv, DOOM_VERT *tp)
  81. #else
  82. local void reject_test_point(lndx,d,ndiv,tp)
  83. int lndx;
  84. int d, ndiv;
  85. DOOM_VERT *tp;
  86. #endif
  87. {
  88.   register DOOM_VERT *vf = &rinfo.verts[rinfo.lines[lndx].fndx],
  89.                      *vt = &rinfo.verts[rinfo.lines[lndx].tndx];
  90.  
  91.   tp->x = (long)vf->x + d*((long)vt->x-vf->x)/ndiv;
  92.   tp->y = (long)vf->y + d*((long)vt->y-vf->y)/ndiv;
  93. }
  94.  
  95.  
  96. /******************************************************************************
  97.     ROUTINE:    reject_block_los(vf,vt,lndx)
  98.     WRITTEN BY:    Robert Fenske, Jr.
  99.     CREATED:    June 1994
  100.     DESCRIPTION:    This routine returns whether the input line lndx
  101.             blocks the view of the point vt from the point vf.
  102.             This is equivalent to determining if the lndx line
  103.             intersects the segment defined by vf and vt.  The
  104.             intersection point is not needed, only the knowledge
  105.             that such an intersection exists.  For such an
  106.             intersection to exist, the points vf and vt must lie on
  107.             opposite sides of the lndx line, and the vertices of
  108.             the lndx line must lie on opposite sides of the vf-vt
  109.             segment.  Given that the line is Ax + By + C = 0 and
  110.             a vertex is (Vx,Vy), the intersection of the line
  111.             and the shortest-distance line from the vertex to the
  112.             line is given by
  113.                 Xi = Vx - b * d
  114.                 Yi = Vy - a * d
  115.             where a = B/(A^2+B^2)^.5, b = A/(A^2+B^2)^.5,
  116.             c = C/(A^2+B^2)^.5, and d = a*Vx + b*Vy + c.  Since
  117.             the directional information can be obtained from
  118.             Xi - Vx = Vx - b*d - Vx = -b*d and
  119.             Yi - Vx = Vy - a*d - Vy = -a*d, only d is needed to
  120.             determine which side the vertex lies on.  Thus only
  121.             the sign (-1, 0, or +1) of d = (A*Vx + B*Vx + C) /
  122.             (A^2 + B^2)^.5 needs to be considered.  This simple
  123.             matrix can be used to determine the side:
  124.                 "from"       "to" vertex
  125.                 vertex    left    on    right
  126.  
  127.                 left    left    left    both
  128.                 on    left    ?    right
  129.                 right    both    right    right
  130.             For the ? case, the line's directional information must
  131.             be used to determine the "sidedness".  Right is denoted
  132.             with 0, left denoted by 1, and both denoted by -1.
  133.             A, B, C, and d are calculated only when required to
  134.             enhance the speed of the routine.  For the line of
  135.             sight to be blocked the "both" case must occur for
  136.             the lndx line with repect to the vf-vt segment and for
  137.             the vf-vt segment with respect to the lndx line.
  138. ******************************************************************************/
  139. #if defined(ANSI_C)
  140. local int reject_block_los(DOOM_VERT *vf, DOOM_VERT *vt, int lndx)
  141. #else
  142. local int reject_block_los(vf,vt,lndx)
  143. DOOM_VERT *vf, *vt;
  144. int lndx;
  145. #endif
  146. {
  147.   static int rightleft[3][3] = { {  1,  1, -1 },
  148.                                  {  1, -2,  0 },
  149.                                  { -1,  0,  0 } };
  150.   static DOOM_VERT lvf, lvt;            /* last vertices */
  151.   static long A, B, C;                /* describes los line */
  152.   DOOM_VERT *lf = &rinfo.verts[rinfo.lines[lndx].fndx],/* test line vertices */
  153.             *lt = &rinfo.verts[rinfo.lines[lndx].tndx];
  154.   long pfd, ptd;
  155.   register int fsv, tsv, fsl, tsl;        /* "from"/"to" vertex sides */
  156.  
  157.   if (lvf.x != vf->x || lvt.x != vt->x ||
  158.       lvf.y != vf->y || lvt.y != vt->y) {    /* update A,B,C if have to */
  159.     A = -((long)vt->y - vf->y);            /* partition line is */
  160.     B = (long)vt->x - vf->x;            /* Ax + By + C = 0   */
  161.     C = (long)vt->y*vf->x - (long)vt->x*vf->y;
  162.     lvf = *vf;                    /* save new vertices */
  163.     lvt = *vt;
  164.   }
  165.   pfd = A*lf->x + B*lf->y + C;
  166.   fsv = (pfd>=0)-(pfd<=-0);            /* "from" vertex side */
  167.   ptd = A*lt->x + B*lt->y + C;
  168.   tsv = (ptd>=0)-(ptd<=-0);            /* "to" vertex side */
  169.   pfd = rinfo.A[lndx]*vf->x + rinfo.B[lndx]*vf->y + rinfo.C[lndx];
  170.   fsl = (pfd>=0)-(pfd<=-0);            /* "from" vertex side */
  171.   ptd = rinfo.A[lndx]*vt->x + rinfo.B[lndx]*vt->y + rinfo.C[lndx];
  172.   tsl = (ptd>=0)-(ptd<=-0);            /* "to" vertex side */
  173.   return rightleft[1-fsv][1-tsv]==-1 && rightleft[1-fsl][1-tsl]==-1;
  174. }
  175.  
  176.  
  177. /******************************************************************************
  178.     ROUTINE:    reject_test_los(l1,l2)
  179.     WRITTEN BY:    Robert Fenske, Jr.
  180.     CREATED:    June 1994
  181.     DESCRIPTION:    This routine tests the line of sight between line l1
  182.             and line l2.  It does this this by checking if any
  183.             one-sided line blocks the view of l2 from l1.  Two-
  184.             sided lines are regarded as transparent in all cases.
  185.             Each line is checked at a number of points, based on
  186.             the ndiv field of rinfo.  Test points are created for
  187.             l1 and l2 and the line of sight is checked between
  188.             these points.  Sector floor and ceiling height are
  189.             ignored.  The blockmap is used to determine the lines
  190.             that potentially block the line of sight between the
  191.             test points; this greatly reduces the number of lines
  192.             that need to be checked.
  193. ******************************************************************************/
  194. #if defined(ANSI_C)
  195. local boolean reject_test_los(int l1, int l2)
  196. #else
  197. local boolean reject_test_los(l1,l2)
  198. int l1, l2;
  199. #endif
  200. {
  201.   boolean los = FALSE;                /* line-o'-sight flag */
  202.   DOOM_VERT v1, v2;                /* los test vertices */
  203.   long scl = 81920L/(100+rinfo.blockmap[3]);    /* line following scaling */
  204.   long size = 0x80*scl;                /* block size (map coords) */
  205.   long xcc, xcl;
  206.   long xf,yf, xt,yt;
  207.   long xd, yd;                    /* x direction, y direction */
  208.   long m;                    /* diagonal line slope */
  209.   int i;
  210.   int p = 0;                    /* increment to next block */
  211.   int c = 0;                    /* # blocks to consider */
  212.   unsigned short *ub;
  213.   register long b;                /* blockmap block # */
  214.   register int d1, d2;
  215.   register long l;
  216.  
  217.   for (d1 = 0; !los && d1 <= rinfo.ndiv; d1++) {/* do l1's test points */
  218.     reject_test_point(l1,d1,rinfo.ndiv,&v1);
  219.     xf = scl*((long)v1.x-(long)rinfo.blockmap[0]);
  220.     yf = scl*((long)v1.y-(long)rinfo.blockmap[1]);
  221.     for (d2 = 0; !los && d2 <= rinfo.ndiv; d2++) {/* do l2's test points */
  222.       reject_test_point(l2,d2,rinfo.ndiv,&v2);
  223.       los = TRUE;
  224.       xt = scl*((long)v2.x-(long)rinfo.blockmap[0]);
  225.       yt = scl*((long)v2.y-(long)rinfo.blockmap[1]);
  226.       xd = sgn(xt-xf), yd = sgn(yt-yf);
  227.       switch (2*(xf/size == xt/size) + (yf/size == yt/size)) {
  228.        case  0: c=0,                      p=yd*rinfo.blockmap[2];/* diag ln */
  229.        bcase 1: c=abs((int)(xt/size-xf/size))+1, p=xd;    /* horizontal line */
  230.        bcase 2: c=abs((int)(yt/size-yf/size))+1, p=yd*rinfo.blockmap[2];/* */
  231.        bcase 3: c=0+1,                    p=1;    /* start,end in same block */
  232.       }
  233.       b = xf/size + rinfo.blockmap[2]*(yf/size);/* start @ this block */
  234.       for (i = 0; i < c; i++, b+=p) {        /* check special cases */
  235.         ub = (unsigned short *)&rinfo.blockmap[4+b];
  236.         for (l = *ub+1; rinfo.blockmap[l] != -1; l++)
  237.           if (!two_sided(rinfo.blockmap[l]) &&    /* consider only 1-sided */
  238.               reject_block_los(&v1,&v2,rinfo.blockmap[l])) {/* this one- */
  239.             los = FALSE;            /* sided blocks view, so */
  240.             goto next_point;            /* check no further      */
  241.           }
  242.       }
  243.       if (c == 0) {                /* handle diagonal lines */
  244.         m = scl*(yt-yf)/(xt-xf);        /* spanning > 1 block    */
  245.         if (m == 0) m = sgn(yt-yf)*sgn(xt-xf);    /* force a min non-0 slope */
  246.         xcl = xf;
  247.         if (yd == -1) xcc = xf + scl*((yf/size)*size -    1 - yf)/m;
  248.         else          xcc = xf + scl*((yf/size)*size + size - yf)/m;
  249.         do {
  250.           for (c = 0; c <= abs((int)(xcc/size - xcl/size)); c++, b+=xd) {
  251.             ub = (unsigned short *)&rinfo.blockmap[4+b];
  252.             for (l = *ub+1; rinfo.blockmap[l] != -1; l++)
  253.               if (!two_sided(rinfo.blockmap[l]) &&/* consider only 1-sided */
  254.                   reject_block_los(&v1,&v2,rinfo.blockmap[l])) {/* this one- */
  255.                 los = FALSE;            /* sided blocks view, so     */
  256.                 goto next_point;        /* check no further          */
  257.               }
  258.           }
  259.           b += p-xd;
  260.           xcl = xcc, xcc += yd*scl*size/m;
  261.           if (xd*xcc > xd*xt) xcc = xt;        /* don't overrun endpoint */
  262.         } while (xd*xcl < xd*xt);
  263.       }
  264. next_point: ;
  265.     }
  266.   }
  267.   return los;
  268. }
  269.  
  270.  
  271. /******************************************************************************
  272.     ROUTINE:    reject_mark_los(l1,l2)
  273.     WRITTEN BY:    Robert Fenske, Jr.
  274.     CREATED:    June 1994
  275.     DESCRIPTION:    This routine checks the line of sight between lines l1
  276.             and l2.  Since the Reject array is sector-based, the
  277.             decision to test the line of sight is based on the
  278.             state of the Reject and Checked arrays for the sectors
  279.             asociated with the side(s) of the lines.  If any pair
  280.             of sides are in the same sector, the Checked array
  281.             is set and the Reject array is untouched since the
  282.             sides are trivially in sight of each other.  Otherwise,
  283.             if the pair is still flagged as not in line of sight
  284.             or the pair has not been checked yet, the line of
  285.             sight test is performed.  If the line of sight test
  286.             fails, the Reject array is flagged as such.
  287.             Reject[s1][s2] and Reject[s2][s1] are flagged at the
  288.             same time since the same line of sight condition will
  289.             exist for either sector.
  290. ******************************************************************************/
  291. #if defined(ANSI_C)
  292. local void reject_mark_los(int l1, int l2)
  293. #else
  294. local void reject_mark_los(l1,l2)
  295. int l1, l2;
  296. #endif
  297. {
  298.   boolean tested = FALSE;            /* whether los already tsted */
  299.   boolean los = FALSE;                /* line o' sight flag */
  300.   int s1, s2;                    /* tested sectors */
  301.   int i1, i2;
  302.  
  303.   for (i1 = 0; i1 <= 1; i1++) {            /* check both sides of l1 */
  304.     s1 = i1==0 ? rside_sect(l1) : lside_sect(l1);
  305.     for (i2 = 0; i2 <= 1; i2++) {        /* check both sides of l2 */
  306.       s2 = i2==0 ? rside_sect(l2) : lside_sect(l2);
  307.       if (s1 == s2)                /* just mark as checked */
  308.         set_flag(Checked,s1,s2);        /* since an obvious los */
  309.       else if (get_flag(Reject,s1,s2) != 0 ||    /* if not in line o' sight */
  310.                get_flag(Checked,s1,s2) == 0) {    /* or unchecked, check it  */
  311.         if (los || (!tested && (los = reject_test_los(l1,l2))!=FALSE)) {
  312.           clr_flag(Reject,s1,s2),        /* in line o' sight */
  313.           clr_flag(Reject,s2,s1);
  314.         }else
  315.           set_flag(Reject,s1,s2),        /* not in line o' sight */
  316.           set_flag(Reject,s2,s1);
  317.         set_flag(Checked,s1,s2);        /* now has been checked */
  318.         set_flag(Checked,s2,s1);
  319.         tested = TRUE;                /* los been tested for l1,l2 */
  320.       }
  321.     }
  322.   }
  323. }
  324.  
  325.  
  326. /******************************************************************************
  327.     ROUTINE:    reject_init(lines,nlines,sides,verts,blockmap,ndiv)
  328.     WRITTEN BY:    Robert Fenske, Jr.
  329.     CREATED:    June 1994
  330.     DESCRIPTION:    This routine initializes the reject information block.
  331.             It computes the lines equation constants (where a line
  332.             is defined by Ax + By + C = 0) and finds the number of
  333.             sectors.
  334. ******************************************************************************/
  335. #if defined(ANSI_C)
  336. local void reject_init(DOOM_LINE *lines, long nlines, DOOM_SIDE *sides,
  337.                        DOOM_VERT *verts, DOOM_BLOCKMAP *blockmap, int ndiv)
  338. #else
  339. local void reject_init(lines,nlines,sides,verts,blockmap,ndiv)
  340. DOOM_LINE *lines;
  341. long nlines;
  342. DOOM_SIDE *sides;
  343. DOOM_VERT *verts;
  344. DOOM_BLOCKMAP *blockmap;
  345. int ndiv;
  346. #endif
  347. {
  348.   register DOOM_VERT *vf, *vt;
  349.   register int l;
  350.  
  351.   rinfo.lines = lines;                /* assign these */
  352.   rinfo.nlines = nlines;
  353.   rinfo.sides = sides;
  354.   rinfo.verts = verts;
  355.   rinfo.blockmap = blockmap;
  356.   rinfo.ndiv = ndiv;
  357.   rinfo.A = blockmem(long,rinfo.nlines);
  358.   rinfo.B = blockmem(long,rinfo.nlines);
  359.   rinfo.C = blockmem(long,rinfo.nlines);
  360.   for (l = 0; l < nlines; l++) {        /* compute lines equations */
  361.     vf = &rinfo.verts[rinfo.lines[l].fndx];
  362.     vt = &rinfo.verts[rinfo.lines[l].tndx];
  363.     rinfo.A[l] = -((long)vt->y-vf->y);
  364.     rinfo.B[l] = (long)vt->x-vf->x;
  365.     rinfo.C[l] = (long)vt->y*vf->x - (long)vt->x*vf->y;
  366.   }
  367.   rinfo.nsects = 0;
  368.   for (l = 0; l < nlines; l++)            /* find highest sector # */
  369.     if (rinfo.nsects < rside_sect(l))
  370.       rinfo.nsects = rside_sect(l);
  371.     else if (two_sided(l) && rinfo.nsects < lside_sect(l))
  372.       rinfo.nsects = lside_sect(l);
  373.   rinfo.nsects++;                /* highest+1 --> # sectors */
  374. }
  375.  
  376.  
  377. /******************************************************************************
  378.     ROUTINE:    reject_make(reject,zeroflag,except,lines,nlines,sides,
  379.                         verts,blockmap)
  380.     WRITTEN BY:    Robert Fenske, Jr.
  381.     CREATED:    June 1994
  382.     DESCRIPTION:    This routine generates the REJECT block.  If first
  383.             intializes the information structure needed for the
  384.             calculation routines.  The REJECT resource is allocated
  385.             based on the computed number of sectors.  The
  386.             allocation initializes the Reject array to all zeroes.
  387.             A companion resource is allocated for flags to indicate
  388.             sector pairs that have been checked at least once and
  389.             is initialized as all unchecked.  If zeroflag is TRUE,
  390.             then no line-of-sight processing is done--the routine
  391.             skips directly to the exception list.  Then each sector
  392.             pair that shares a line is marked as checked since the
  393.             pair can trivially see each other.  Then all possible
  394.             unique two-sided line pairs are checked for line of
  395.             sight (i.e., after checking pair l1,l2 then pair l2,l1
  396.             doesn't need checking since the result will be the
  397.             same).  Since a line-o'-sight line must pass through or
  398.             start from a two-sided line for a given sector, only
  399.             two-sided lines need to be checked.  Any sectors
  400.             sharing a two-sided line are immediately marked as
  401.             being in line of sight.  Note that any sectors with
  402.             no two-sided lines will be implicitly flagged as in
  403.             sight of every other sector since they won't be
  404.             checked.  Once all the line are scanned, the exception
  405.             list is processed.  All sector pairs in the exception
  406.             lists are marked with a one.
  407. ******************************************************************************/
  408. #if defined(ANSI_C)
  409. long reject_make(DOOM_REJECT **reject, boolean zeroflag, char *except,
  410.                  DOOM_LINE *lines, long nlines, DOOM_SIDE *sides,
  411.                  DOOM_VERT *verts, DOOM_BLOCKMAP *blockmap)
  412. #else
  413. long reject_make(reject,zeroflag,except,lines,nlines,sides,verts,blockmap)
  414. DOOM_REJECT **reject;
  415. boolean zeroflag;
  416. char *except;
  417. DOOM_LINE *lines;
  418. long nlines;
  419. DOOM_SIDE *sides;
  420. DOOM_VERT *verts;
  421. DOOM_BLOCKMAP *blockmap;
  422. #endif
  423. {
  424.   long size;                    /* # bytes in REJECT block */
  425.   int s1, s2;
  426.   register int l1, l2;
  427.  
  428.   reject_init(lines,nlines,sides,verts,blockmap,3);
  429.   size = ((long)rinfo.nsects*rinfo.nsects+7)/8;    /* # bytes in REJECT block */
  430.   Reject = blockmem(DOOM_REJECT,size);        /* this is REJECT block */
  431.   Checked = blockmem(DOOM_REJECT,size);
  432.   if (!zeroflag) {
  433.     for (l1 = 0; l1 < rinfo.nlines; l1++)    /* first mark all sectors    */
  434.       if (two_sided(l1))            /* sharing a line as checked */
  435.         set_flag(Checked,rside_sect(l1),lside_sect(l1)),/* since obvious los */
  436.         set_flag(Checked,lside_sect(l1),rside_sect(l1));
  437.     for (l1 = 0; l1 < rinfo.nlines; l1++)    /* check all line pairs */
  438.       if (two_sided(l1)) {
  439.         printf("%04d\010\010\010\010",(int)(rinfo.nlines-l1));
  440.         for (l2 = l1+1; l2 < rinfo.nlines; l2++)
  441.           if (two_sided(l2)) reject_mark_los(l1,l2);
  442.       }
  443.   }
  444.   while (except != NULL &&            /* if have exception list    */
  445.          1<=(l1=sscanf(except,"%d-%d",&s1,&s2))) {/* process by setting flag */
  446.     if (l1 == 2)                /* in REJECT for all sector  */
  447.       set_flag(Reject,s1,s2);            /* pairs                     */
  448.     else                    /* (only one sector listed:  */
  449.       for (s2 = 0; s2 < rinfo.nsects; s2++)    /* flag all other sectors    */
  450.         if (s1 != s2)                /* re: this sector)          */
  451.           set_flag(Reject,s1,s2), set_flag(Reject,s2,s1);
  452.     except = strchr(except,',');
  453.     if (except != NULL) except++;
  454.   }
  455.   blockfree(rinfo.A);                /* done with these */
  456.   blockfree(rinfo.B);
  457.   blockfree(rinfo.C);
  458.   blockfree(Checked);                /* done with this */
  459.   *reject = Reject;
  460.   return size;
  461. }
  462.  
  463.